#include "queue_data.h"
#include "comm.h"

#if 0
CircularQueue q;
static int init_flag = 0;
// 初始化队列
void initQueue(CircularQueue *q, int size) {
    q->buffer = (char *)malloc(size);
    if (!q->buffer) {
        perror("Failed to allocate queue buffer");
        exit(1);
    }
    q->head = 0;
    q->tail = 0;
    q->size = size;
    pthread_mutex_init(&q->mutex, NULL);
    pthread_cond_init(&q->not_full, NULL);
    pthread_cond_init(&q->not_empty, NULL);
}

// 判断队列是否满
int isFull() {
    // return ((q->tail + 1) % q->size) == q->head;
    return ((q.tail + 1) % q.size) == q.head;
}

// 判断队列是否为空
int isEmpty() {
    // return q->head == q->tail;
    return q.head == q.tail;
}

// 向队列添加数据
int enqueue(char *data, int len) {
    if(init_flag == 0)
    {
        initQueue(&q, QUEUE_SIZE);
        init_flag = 1;
    }
    // printf("Enqueue: tail=%d, len=%d, q_size=%d\n", q->tail, len, q->size);

    pthread_mutex_lock(&q.mutex);
    // printf("=[%d]===========%s======%p==\n",__LINE__, __func__, &q->mutex);
    // 等待队列有空闲空间
    while (isFull()) {
        pthread_cond_wait(&q.not_full, &q.mutex);
    }

    // printf("=[%d]===========%s========\n",__LINE__, __func__);
    for (int i = 0; i < len; ++i) {
        q.buffer[q.tail] = data[i];
        q.tail = (q.tail + 1) % q.size;
    }

     // 通知消费者队列非空
    pthread_cond_signal(&q.not_empty);
    pthread_mutex_unlock(&q.mutex);

    return 0;
}

// 从队列中取出数据
int dequeue(char *data, int len) {
    if(init_flag == 0)
    {
        initQueue(&q, QUEUE_SIZE);
        init_flag = 1;
    }
    // printf("dequeue: tail=%d, len=%d.q_szie=%d\n", q->tail, len, q->size);

    pthread_mutex_lock(&q.mutex);
    // printf("=[%d]===========%s======%p==\n",__LINE__, __func__, &q->mutex);
    while (isEmpty()) {
        pthread_cond_wait(&q.not_empty, &q.mutex);
    }

    // printf("=[%d]===========%s========\n",__LINE__, __func__);
    for (int i = 0; i < len; ++i) {
        data[i] = q.buffer[q.head];
        q.head = (q.head + 1) % q.size;
    }

    // 通知生产者队列有空余
    pthread_cond_signal(&q.not_full);
    pthread_mutex_unlock(&q.mutex);
    return 0;
}

// 销毁队列
void destroyQueue() {
    free(q.buffer);
}

#endif
CircularQueue q;
static int init_flag = 0;

void init_queue(CircularQueue *q){
    q->head = 0;
    q->tail = 0;
    q->size = 0;
    pthread_mutex_init(&q->mutex, NULL);
    pthread_cond_init(&q->not_full, NULL);
    pthread_cond_init(&q->not_empty, NULL);
}

// 存入数据到环形队列
void enqueue(void* data, size_t data_size) {
    if(init_flag == 0)
    {
        init_queue(&q);
        init_flag = 1;
    }
    // info();
    pthread_mutex_lock(&q.mutex);
    // info();
    // 如果队列剩余空间不足，将覆盖旧数据
    while (q.size + data_size + sizeof(size_t) > QUEUE_SIZE) {
        // pthread_cond_wait(&q.not_full, &q.mutex);
        size_t old_data_size;
        // 先读取头部数据的大小，跳过头部旧数据
        memcpy(&old_data_size, &q.buffer[q.head], sizeof(size_t));
        q.head = (q.head + sizeof(size_t) + old_data_size) % QUEUE_SIZE;
        q.size -= (sizeof(size_t) + old_data_size);
    }

    // 先存入数据大小
    memcpy(&q.buffer[q.tail], &data_size, sizeof(size_t));
    q.tail = (q.tail + sizeof(size_t)) % QUEUE_SIZE;
    q.size += sizeof(size_t);

    // 再存入实际数据
    if (q.tail + data_size <= QUEUE_SIZE) {
        memcpy(&q.buffer[q.tail], data, data_size);  // 数据不跨界，直接拷贝
    } else {
        size_t part1_size = QUEUE_SIZE - q.tail;
        memcpy(&q.buffer[q.tail], data, part1_size);   // 第一部分
        memcpy(&q.buffer[0], (char*)data + part1_size, data_size - part1_size);  // 第二部分
    }
    q.tail = (q.tail + data_size) % QUEUE_SIZE;
    q.size += data_size;

    pthread_cond_signal(&q.not_empty);  // 通知消费者有数据
    pthread_mutex_unlock(&q.mutex);
}

// 从环形队列中取出数据
void* dequeue(size_t* data_size) {
    if(init_flag == 0)
    {
        init_queue(&q);
        init_flag = 1;
    }
    info();
    pthread_mutex_lock(&q.mutex);

    info();
    // 等待直到有数据可以取出
    while (q.size == 0) {
        pthread_cond_wait(&q.not_empty, &q.mutex);
    }

    // 先取出数据大小
    memcpy(data_size, &q.buffer[q.head], sizeof(size_t));
    q.head = (q.head + sizeof(size_t)) % QUEUE_SIZE;
    q.size -= sizeof(size_t);

    // 分配内存用于存放取出的数据
    void* data = malloc(*data_size);

    // 取出实际数据
    if (q.head + *data_size <= QUEUE_SIZE) {
        memcpy(data, &q.buffer[q.head], *data_size);  // 数据不跨界，直接拷贝
    } else {
        size_t part1_size = QUEUE_SIZE - q.head;
        memcpy(data, &q.buffer[q.head], part1_size);   // 第一部分
        memcpy((char*)data + part1_size, &q.buffer[0], *data_size - part1_size);  // 第二部分
    }
    q.head = (q.head + *data_size) % QUEUE_SIZE;
    q.size -= (*data_size);

    pthread_cond_signal(&q.not_full);  // 通知生产者有空间可用
    pthread_mutex_unlock(&q.mutex);

    return data;
}
